//===============================================================================
// Microsoft patterns & practices
// Web Client Software Factory
//-------------------------------------------------------------------------------
// Copyright (C) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//-------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WCSFContrib.PageFlow;
using WCSFContrib.PageFlow.Xml.Tests.Mocks;
using WCSFContrib.PageFlow.Configuration;
using WCSFContrib.PageFlow.Utils;

namespace WCSFContrib.PageFlow.Xml.Tests
{
    [TestClass]
    public class XmlPageFlowProviderFixture
    {
        private static IDictionary<string, NavigationGraph> _navigationGraphs;
        
        [ClassInitialize]
        public static void SetUp(TestContext testContext)
        {
            AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory);

            _navigationGraphs = new Dictionary<string, NavigationGraph>();
            NavigationGraph navigationGraphUnconstrained = new MockUnconstrainedXmlPageFlowNavigationGraph();
            NavigationGraph navigationGraphConstrained = new MockConstrainedXmlPageFlowNavigationGraph();
            
            _navigationGraphs.Add(navigationGraphUnconstrained.PageFlowType.AssemblyQualifiedName, navigationGraphUnconstrained);
            _navigationGraphs.Add(navigationGraphConstrained.PageFlowType.AssemblyQualifiedName, navigationGraphConstrained);
        }

        [TestMethod]
        public void CanCreateNew()
        {
            IPageFlowProvider provider =
                new XmlPageFlowProvider(new MockPageFlowFactory(),
                                                       new MockPageFlowInstanceStore(string.Empty));

            Assert.IsNotNull(provider);
            Assert.IsTrue(provider is XmlPageFlowProvider);
        }

        [TestMethod]
        [DeploymentItem("Web.config")]
        public void CanCreateNewUsingConfigurationSection()
        {
            string storeType =
                string.Format("{0}, {1}", typeof(MockPageFlowInstanceStoreWithTokenProvider), typeof(MockPageFlowInstanceStoreWithTokenProvider).Assembly.FullName);
            string tokenProviderType =
                string.Format("{0}, {1}", typeof(MockPageFlowCorrelationTokenProvider), typeof(MockPageFlowCorrelationTokenProvider).Assembly.FullName);
            PageFlowInstanceStoreProviderSection storeSection = new PageFlowInstanceStoreProviderSection(storeType, null);
            PageFlowInstanceCorrelationTokenProviderSection tokenSection = new PageFlowInstanceCorrelationTokenProviderSection(tokenProviderType);

            IPageFlowProvider provider = new XmlPageFlowProvider(storeSection, tokenSection);

            Assert.IsNotNull(provider);
            Assert.IsTrue(provider is XmlPageFlowProvider);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void PageFlowInstanceStoreProviderCannotBeNull()
        {
            new XmlPageFlowProvider(null, new PageFlowInstanceCorrelationTokenProviderSection());
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void PageFlowInstanceCorrelationTokenProviderCannotBeNull()
        {
            new XmlPageFlowProvider(new PageFlowInstanceStoreProviderSection(), null);
        }

        [TestMethod]
        public void ShouldReturnInstanceFromStoreIfItExists()
        {
            IPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService());
            IPageFlow flow = factory.GetPageFlow(typeof(MockConstrainedPageFlow));
            IPageFlowInstanceStore store = new MockPageFlowInstanceStore(string.Empty);
            store.Add(flow);
            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                IPageFlow pageFlow = provider.GetPageFlow(typeof(MockConstrainedPageFlow));

                Assert.AreEqual(flow.Id, pageFlow.Id);
            }
        }

        [TestMethod]
        public void ShouldReturnNewInstanceIfItIsntAvailableOnStoreAndSaveInstanceOnStore()
        {
            IPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService());
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                IPageFlow pageFlow = provider.GetPageFlow(typeof(MockConstrainedPageFlow));

                Assert.IsNotNull(pageFlow);
                Assert.IsTrue(store.ContainsKey(typeof(MockConstrainedPageFlow)));
                Assert.AreSame(store[typeof(MockConstrainedPageFlow)], pageFlow);
            }
        }

        [TestMethod]
        public void ShouldGetInstanceById()
        {
            IPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService());
            IPageFlow flow = factory.GetPageFlow(typeof(MockConstrainedPageFlow));
            flow.Start();
            flow.Suspend();
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);
            store.Add(flow);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                IPageFlow pageFlow = provider.GetPageFlow(flow.Id);

                Assert.AreEqual(flow.Id, pageFlow.Id);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(PageFlowException))]
        public void ShouldThrowIfGetInstanceByIdAndInstanceNotFoundInStore()
        {
            IPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService());
            IPageFlow flow = factory.GetPageFlow(typeof(MockConstrainedPageFlow));
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                IPageFlow pageFlow = provider.GetPageFlow(flow.Id);
            }
        }

        [TestMethod]
        public void ShouldRemoveFlowFromStoreWhenOnPageFlowAborted()
        {
            IPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService());
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                IPageFlow pageFlow = provider.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();

                pageFlow.Abort(false);

                Assert.AreEqual(Guid.Empty, store.GetLastRunningInstance());
                Assert.IsFalse(store.ContainsKey(typeof(MockUnconstrainedPageFlow)));
            }
        }

        [TestMethod]
        public void ShouldSetInstanceAsRunningWhenStarted()
        {
            IPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService());
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                IPageFlow pageFlow = provider.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();

                Assert.IsNotNull(store.GetLastRunningInstance());
                Assert.AreEqual(store.GetLastRunningInstance(), pageFlow.Id);
                Assert.IsTrue(store.ContainsKey(typeof(MockUnconstrainedPageFlow)));
            }
        }

        [TestMethod]
        public void ShouldRemoveInstanceFromStoreWhenCompleted()
        {
            IPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService());
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                IPageFlow pageFlow = provider.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Complete();

                Assert.AreEqual(Guid.Empty, store.GetLastRunningInstance());
                Assert.IsFalse(store.ContainsKey(typeof(MockUnconstrainedPageFlow)));
            }
        }

        [TestMethod]
        public void ShouldMarkInstanceAsNotRunningAndKeepItOnStoreWhenSuspended()
        {
            IPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService());
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                IPageFlow pageFlow = provider.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Suspend();

                Assert.AreEqual(Guid.Empty, store.GetLastRunningInstance());
                Assert.IsTrue(store.ContainsKey(typeof(MockUnconstrainedPageFlow)));
            }
        }

        [TestMethod]
        public void ProcessRequestShouldRedirectConstrainedPageFlow()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            IPageFlowDefinitionCatalog catalog = new PageFlowDefinitionCatalog();
            IPageFlowDefinition definition = new MockConstrainedPageFlowDefinition();
            catalog.Add(definition);

            MockPageFlow pageFlowInstance = new MockPageFlow(definition);
            factory.AddPageFlow(typeof(MockPageFlow), pageFlowInstance);
            store.Add(pageFlowInstance);
            Page currentPage = new Page("PageC", "~/pageC.aspx");
            pageFlowInstance.CurrentPage = currentPage;
            store.SetPageFlowRunning(pageFlowInstance);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result = provider.ProcessRequest("~/pageA.aspx");

                Assert.IsTrue(result.ShouldRedirect);
                Assert.AreEqual("~/pageC.aspx", result.RedirectUrl);
                Assert.AreEqual(currentPage, pageFlowInstance.CurrentPage);
            }
        }

        [TestMethod]
        public void PageFlowAbandonedEventCallsAbort()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();

            IPageFlowDefinitionCatalog catalog = new PageFlowDefinitionCatalog();
            MockConstrainedPageFlowDefinition definition = new MockConstrainedPageFlowDefinition();
            definition.Abandonable = AbandonBehavior.AllowAndDiscardInstance;
            catalog.Add(definition);

            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            MockPageFlow pageFlowInstance = new MockPageFlow(definition);
            factory.AddPageFlow(typeof(MockPageFlow), pageFlowInstance);
            store.Add(pageFlowInstance);
            Page currentPage = new Page("PageC", "~/pageC.aspx");
            pageFlowInstance.CurrentPage = currentPage;

            store.SetPageFlowRunning(pageFlowInstance);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result = provider.ProcessRequest("http://localhost/outsidePageFlowPage.aspx");
            }

            Assert.IsTrue(pageFlowInstance.AbortCalled);
        }

        [TestMethod]
        public void ShouldRedirectToCurrentPageWhenRequestingNonPageFlowPageAndPageFlowIsNotAbandonable()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();

            IPageFlowDefinitionCatalog catalog = new PageFlowDefinitionCatalog();
            MockConstrainedPageFlowDefinition definition = new MockConstrainedPageFlowDefinition();
            definition.Abandonable = AbandonBehavior.Prevent;
            catalog.Add(definition);

            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            MockPageFlow pageFlowInstance = new MockPageFlow(definition);
            factory.AddPageFlow(typeof(MockPageFlow), pageFlowInstance);
            store.Add(pageFlowInstance);
            Page currentPage = new Page("PageC", "~/pageC.aspx");
            pageFlowInstance.CurrentPage = currentPage;
            store.SetPageFlowRunning(pageFlowInstance);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result = provider.ProcessRequest("http://localhost/outsidePageFlowPage.aspx");
                Assert.IsTrue(result.ShouldRedirect);
                Assert.AreEqual(currentPage.Url, result.RedirectUrl);
            }
        }

        [TestMethod]
        public void ShouldSuspendWhenRequestingNonPageFlowPageAndPageFlowIsAbandonableReusable()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();

            IPageFlowDefinitionCatalog catalog = new PageFlowDefinitionCatalog();
            MockConstrainedPageFlowDefinition definition = new MockConstrainedPageFlowDefinition();
            definition.Abandonable = AbandonBehavior.AllowAndSaveInstance;
            catalog.Add(definition);

            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            MockPageFlow pageFlowInstance = new MockPageFlow(definition);
            factory.AddPageFlow(typeof(MockPageFlow), pageFlowInstance);
            store.Add(pageFlowInstance);
            Page currentPage = new Page("PageC", "~/pageC.aspx");
            pageFlowInstance.CurrentPage = currentPage;
            store.SetPageFlowRunning(pageFlowInstance);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result = provider.ProcessRequest("http://localhost/outsidePageFlowPage.aspx");
                Assert.IsFalse(result.ShouldRedirect);
            }

            Assert.IsTrue(pageFlowInstance.SuspendCalled);
        }

        [TestMethod]
        public void ShouldResumeOnCurrentPageWhenRequestingPageFlowPageAndPageFlowIsAbandonableReusable()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();

            MockConstrainedPageFlowDefinition definition = new MockConstrainedPageFlowDefinition();
            definition.Abandonable = AbandonBehavior.AllowAndSaveInstance;
            PageFlowDirectory.Catalog.Add(definition);

            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            MockPageFlow pageFlowInstance = new MockPageFlow(definition);
            factory.AddPageFlow(typeof(MockPageFlow), pageFlowInstance);
            store.Add(pageFlowInstance);
            Page currentPage = new Page("PageC", "~/pageC.aspx");
            pageFlowInstance.CurrentPage = currentPage;
            store.SetPageFlowRunning(pageFlowInstance);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result1 = provider.ProcessRequest("~/outsidePageFlowPage.aspx");
                Assert.AreEqual(PageFlowStatus.Suspended, pageFlowInstance.Status);

                ProcessResult result2 = provider.ProcessRequest("~/pageA.aspx");
                Assert.IsFalse(result2.ShouldRedirect);
                Assert.AreEqual(currentPage.Url, pageFlowInstance.CurrentPage.Url);
                Assert.AreEqual(PageFlowStatus.Running, pageFlowInstance.Status);
            }

            PageFlowDirectory.Catalog.Remove(definition);
        }

        [TestMethod]
        public void ShouldRedirectUserToNotStartedPageWhenRequestingPageFlowPageAndPageFlowNotStarted()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();

            MockConstrainedPageFlowDefinition definition = new MockConstrainedPageFlowDefinition();
            definition.Abandonable = AbandonBehavior.Prevent;
            PageFlowDirectory.Catalog.Add(definition);

            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result = provider.ProcessRequest("~/pageA.aspx");
                Assert.IsTrue(result.ShouldRedirect);
                Assert.AreEqual(definition.NotRunningRedirect, result.RedirectUrl);

            }

            PageFlowDirectory.Catalog.Remove(definition);
        }

        [TestMethod]
        public void ShouldResumePageFlow2WhenJumpingFromPageFlow1AndSuspendPageFlow1()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            MockConfigurablePageFlowDefinition definition1 = CreatePageFlowDef1();
            PageFlowDirectory.Catalog.Add(definition1);
            MockConfigurablePageFlowDefinition definition2 = CreatePageFlowDef2();
            PageFlowDirectory.Catalog.Add(definition2);

            MockPageFlow pageFlowInstance1 = new MockPageFlow(definition1);
            pageFlowInstance1.CurrentPage = new Page("A", "~/a.aspx");

            MockPageFlow pageFlowInstance2 = new MockPageFlow(definition2);
            pageFlowInstance2.CurrentPage = new Page("Z", "~/z.aspx");
            pageFlowInstance2.Suspend();

            factory.AddPageFlow(typeof(MockConstrainedPageFlow), pageFlowInstance1);
            factory.AddPageFlow(typeof(MockConstrainedPageFlow2), pageFlowInstance2);

            store.Add(pageFlowInstance1);
            store.Add(pageFlowInstance2);
            store.SetPageFlowRunning(pageFlowInstance1);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result = provider.ProcessRequest("~/z.aspx");
                Assert.AreEqual(PageFlowStatus.Suspended, pageFlowInstance1.Status);
                Assert.AreEqual(PageFlowStatus.Running, pageFlowInstance2.Status);

            }

            PageFlowDirectory.Catalog.Remove(definition1);
            PageFlowDirectory.Catalog.Remove(definition2);
        }

        [TestMethod]
        public void ShouldRedirectToNotStartedWhenJumpingFromPageFlow1ToANonStartedPageFlow2()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            MockConfigurablePageFlowDefinition definition1 = CreatePageFlowDef1();
            PageFlowDirectory.Catalog.Add(definition1);
            MockConfigurablePageFlowDefinition definition2 = CreatePageFlowDef2();
            PageFlowDirectory.Catalog.Add(definition2);

            MockPageFlow pageFlowInstance1 = new MockPageFlow(definition1);
            pageFlowInstance1.CurrentPage = new Page("A", "~/a.aspx");

            MockPageFlow pageFlowInstance2 = new MockPageFlow(definition2);

            factory.AddPageFlow(typeof(MockConstrainedPageFlow), pageFlowInstance1);
            factory.AddPageFlow(typeof(MockConstrainedPageFlow2), pageFlowInstance2);

            store.Add(pageFlowInstance1);
            store.SetPageFlowRunning(pageFlowInstance1);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result = provider.ProcessRequest("~/z.aspx");
                Assert.AreEqual(PageFlowStatus.Suspended, pageFlowInstance1.Status);
                Assert.AreEqual(PageFlowStatus.NotStarted, pageFlowInstance2.Status);
                Assert.IsTrue(result.ShouldRedirect);
                Assert.AreEqual(definition2.NotRunningRedirect, result.RedirectUrl);

            }

            PageFlowDirectory.Catalog.Remove(definition1);
            PageFlowDirectory.Catalog.Remove(definition2);
        }

        [TestMethod]
        public void ShouldRedirectToCurrentPageWhenJumpingFromPageFlow1ToARunningPageFlow2()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            MockConfigurablePageFlowDefinition definition1 = CreatePageFlowDef1();
            PageFlowDirectory.Catalog.Add(definition1);
            MockConfigurablePageFlowDefinition definition2 = CreatePageFlowDef2();
            PageFlowDirectory.Catalog.Add(definition2);

            MockPageFlow pageFlowInstance1 = new MockPageFlow(definition1);
            pageFlowInstance1.CurrentPage = new Page("A", "~/a.aspx");
            pageFlowInstance1.Start();

            MockPageFlow pageFlowInstance2 = new MockPageFlow(definition2);
            pageFlowInstance2.CurrentPage = new Page("X", "~/x.aspx");
            pageFlowInstance2.Start();

            factory.AddPageFlow(typeof(MockConstrainedPageFlow), pageFlowInstance1);
            factory.AddPageFlow(typeof(MockConstrainedPageFlow2), pageFlowInstance2);

            store.Add(pageFlowInstance1);
            store.Add(pageFlowInstance2);
            store.SetPageFlowRunning(pageFlowInstance1);
            store.SetPageFlowRunning(pageFlowInstance2);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result = provider.ProcessRequest("~/z.aspx");
                Assert.AreEqual(PageFlowStatus.Suspended, pageFlowInstance1.Status);
                Assert.AreEqual(PageFlowStatus.Running, pageFlowInstance2.Status);
                Assert.IsTrue(result.ShouldRedirect);
                Assert.AreEqual(pageFlowInstance2.CurrentPage.Url, result.RedirectUrl);

            }

            PageFlowDirectory.Catalog.Remove(definition1);
            PageFlowDirectory.Catalog.Remove(definition2);
        }

        private static MockConfigurablePageFlowDefinition CreatePageFlowDef1()
        {
            MockConfigurablePageFlowDefinition definition1 = new MockConfigurablePageFlowDefinition();
            definition1.Abandonable = AbandonBehavior.AllowAndSaveInstance;
            definition1.Constrained = true;
            definition1.AddPage(new Page("A", "~/a.aspx"));
            definition1.AddPage(new Page("B", "~/b.aspx"));
            definition1.PageFlowType = typeof(MockConstrainedPageFlow);
            return definition1;
        }

        private static MockConfigurablePageFlowDefinition CreatePageFlowDef2()
        {
            MockConfigurablePageFlowDefinition definition2 = new MockConfigurablePageFlowDefinition();
            definition2.Abandonable = AbandonBehavior.AllowAndSaveInstance;
            definition2.Constrained = true;
            definition2.AddPage(new Page("X", "~/x.aspx"));
            definition2.AddPage(new Page("Y", "~/y.aspx"));
            definition2.AddPage(new Page("Z", "~/z.aspx"));
            definition2.PageFlowType = typeof(MockConstrainedPageFlow2);
            return definition2;
        }

        [TestMethod]
        public void ShouldSetPageFlowStateWhenUnconstrainedPageFlowPageIsRequested()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();

            IPageFlowDefinitionCatalog catalog = new PageFlowDefinitionCatalog();
            MockUnconstrainedPageFlowDefinition definition = new MockUnconstrainedPageFlowDefinition();
            definition.Abandonable = AbandonBehavior.AllowAndDiscardInstance;
            catalog.Add(definition);

            IPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            MockPageFlow pageFlowInstance = new MockPageFlow(definition);
            factory.AddPageFlow(typeof(MockPageFlow), pageFlowInstance);
            pageFlowInstance.CurrentPage = new Page("PageC", "~/pageC.aspx");
            store.Add(pageFlowInstance);

            store.SetPageFlowRunning(pageFlowInstance);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result = provider.ProcessRequest("~/pageA.aspx");

                Assert.IsFalse(result.ShouldRedirect);
                Assert.AreEqual("pageA", pageFlowInstance.CurrentPage.Name);
            }
        }

        [TestMethod]
        public void ShouldNotRedirectOnConstrainedPageFlowIfRequestingCurrentPage()
        {
            MockPageFlowFactory factory = new MockPageFlowFactory();

            IPageFlowDefinitionCatalog catalog = new PageFlowDefinitionCatalog();
            MockConstrainedPageFlowDefinition definition = new MockConstrainedPageFlowDefinition();
            catalog.Add(definition);

            IPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            MockPageFlow pageFlowInstance = new MockPageFlow(definition);
            factory.AddPageFlow(typeof(MockPageFlow), pageFlowInstance);
            pageFlowInstance.CurrentPage = new Page("PageA", "~/pageA.aspx");
            store.Add(pageFlowInstance);
            store.SetPageFlowRunning(pageFlowInstance);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                ProcessResult result = provider.ProcessRequest("~/pageA.aspx");
                Assert.IsFalse(result.ShouldRedirect);
            }
        }

        [TestMethod]
        public void ShouldMantainPageFlowStatusInDifferentRequestsWhenPageFlowIsNotStarted()
        {
            IPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService());
            MockPageFlowInstanceStore store = new MockPageFlowInstanceStore(null);

            using (XmlPageFlowProvider provider = new XmlPageFlowProvider(factory, store))
            {
                IPageFlow pageFlow1 = provider.GetPageFlow(typeof(MockConstrainedPageFlow));
                Assert.AreEqual(PageFlowStatus.NotStarted, pageFlow1.Status);

                IPageFlow pageFlow2 = provider.GetPageFlow(typeof(MockConstrainedPageFlow));
                Assert.AreEqual(PageFlowStatus.NotStarted, pageFlow2.Status);
            }
        }
    }

    class MockPageFlowInstanceStoreWithTokenProvider : MockPageFlowInstanceStore
    {
        public MockPageFlowInstanceStoreWithTokenProvider(string connectionString, IPageFlowCorrelationTokenProvider token)
            : base(connectionString)
        {
            
        }
    }
}
